using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.ComponentModel.Design;

namespace Ferpect.GameComponents.Design
{
    public class OwnerPropertyDescriptor : PropertyDescriptorWrapper
    {
        private PropertyDescriptor innerDescriptor;
        private object propertyOwner;
        private IComponent viewControl;
        private IComponentChangeService changeService;

        /// <summary>
        /// There are other base constructors that can be used add or customize attributes.
        /// </summary>
        /// <param name="innerDescriptor">The descriptor from the owner object.</param>
        /// <param name="propertyOwner">The innerDescriptor property's owner.</param>
        public OwnerPropertyDescriptor(PropertyDescriptor innerDescriptor, object propertyOwner, IComponent viewControl) : base(innerDescriptor)
        {
            if (innerDescriptor == null) throw new ArgumentNullException("innerDescriptor");
            if (propertyOwner == null) throw new ArgumentNullException("propertyOwner");
            if (viewControl == null) throw new ArgumentNullException("viewControl");

            this.innerDescriptor = innerDescriptor;
            this.propertyOwner = propertyOwner;
            this.viewControl = viewControl;
        }

        public override object GetValue(object component)
        {
            return this.innerDescriptor.GetValue(this.propertyOwner);
        }

        private void OnChanging()
        {
            if (this.changeService == null)
            {
                this.changeService = this.viewControl.Site.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
            }
            if (this.changeService != null)
            {
                this.changeService.OnComponentChanging(this.viewControl, this);
            }
        }

        private void OnChanged()
        {
            if (this.changeService == null)
            {
                this.changeService = this.viewControl.Site.GetService(typeof(IComponentChangeService)) as IComponentChangeService;
            }
            if (this.changeService != null)
            {
                this.changeService.OnComponentChanged(this.viewControl, this, null, null);
            }
        }

        public object Owner
        {
            get
            {
                return this.propertyOwner;
            }
        }

        public override void ResetValue(object component)
        {
            this.OnChanging();
            this.innerDescriptor.ResetValue(this.propertyOwner);
            this.OnChanged();
        }

        public override void SetValue(object component, object value)
        {
            this.OnChanging();
            this.innerDescriptor.SetValue(this.propertyOwner, value);
            this.OnChanged();
        }

        public override bool ShouldSerializeValue(object component)
        {
            return base.ShouldSerializeValue(this.propertyOwner);
        }
    }
}
